﻿// copyright (c) 2025 author:fio66<fio66@foxmail.com>. All rights reserved.
// date: 2025-08-21 14:07:31

#ifndef _FFMPEG_WRAPPER_SRC_DEMUXER_IMPL_H_
#define _FFMPEG_WRAPPER_SRC_DEMUXER_IMPL_H_

#include <atomic>
#include <string_view>
#include <mutex>
#include <condition_variable>
#include <future>
#include <optional>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/pixfmt.h>
};

#include "src/ffmpeg_warpper_export.h"

namespace fio66 {
class DemuxerImpl : public Demuxer {
 public:
  struct ImageData {
    AVPixelFormat pix_fmt;
    uint8_t* img_data[4] = {NULL};
    int img_linesize[4] = {0};
    int img_buffersize = 0;
    int width = 0;
    int height = 0;
  };

 public:
  DemuxerImpl() = default;
  ~DemuxerImpl() { UninitFFMpeg(); }

  bool Demuxing(std::string_view url, MediaDataCallback* callback) final;
  void PauseDemuxing() final;    // 暂停解复用
  void ResumeDemuxing() final;   // 恢复解复用
  void QuitDemuxing() final;     // 退出解复用
  
  // 获取媒体信息
  std::optional<std::variant<AudioInfo, VideoInfo>> GetMediaInfo(MediaType type) final;

  // 进度控制
  double GetCurrentPosition() final;  // 获取当前播放进度，单位为秒
  double GetDuration() final;          // 获取总时长，单位为秒
  bool SeekTo(double position) final;  // 设置播放进度，单位为秒

 private:
  bool WorkThread();
  void UninitFFMpeg();
  void DoSeek();  // 执行实际的seek操作

  bool CallVideo(AVFrame* frame);
  void CallAudio(AVFrame* frame);

  bool DecodePacket(AVCodecContext* codec_ctx, const AVPacket* pkt,
                    AVFrame* frame);

 private:
  std::future<bool> work_thread_future_;
  
  std::atomic_bool run_demuxing_;
  bool pause_state_ = false;                 // 暂停状态标志
  std::mutex pause_mutex_;                   // 保护暂停状态的互斥锁
  std::condition_variable pause_cv_;   
        // 暂停条件变量
  AVFormatContext* fmt_ctx_ = NULL;
  int video_stream_idx_ = -1;
  int audio_stream_idx_ = -1;
  AVCodecContext* video_codec_context_ = NULL;
  AVCodecContext* audio_codec_context_ = NULL;
  AVStream* video_stream_ = NULL;
  AVStream* audio_stream_ = NULL;
  ImageData img_;

  MediaDataCallback* callback_;
  
  // 用于跟踪当前播放位置的成员变量
  int64_t last_video_pts_ = AV_NOPTS_VALUE;  // 上次处理的视频帧时间戳
  int64_t last_audio_pts_ = AV_NOPTS_VALUE;  // 上次处理的音频帧时间戳
  
  // 用于控制seek操作的成员变量
  std::atomic_bool need_seek_ = false;       // 是否需要执行seek操作
  std::atomic<double> target_seek_position_; // 目标seek位置（秒）
};

}  // namespace fio66

#endif  // _FFMPEG_WRAPPER_SRC_DEMUXER_IMPL_H_
